//===----------------------------------------------------------------------===//
//
//                         BusTub
//
// nested_loop_join_executor.cpp
//
// Identification: src/execution/nested_loop_join_executor.cpp
//
// Copyright (c) 2015-2021, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

// 循环join的实现， 即计算笛卡尔积并做筛选
// 我们在init中计算出结果，然后next读取结果
#include "execution/executors/nested_loop_join_executor.h"

namespace bustub {

NestedLoopJoinExecutor::NestedLoopJoinExecutor(ExecutorContext *exec_ctx, const NestedLoopJoinPlanNode *plan,
                                               std::unique_ptr<AbstractExecutor> &&left_executor,
                                               std::unique_ptr<AbstractExecutor> &&right_executor)
    : AbstractExecutor(exec_ctx)
    ,plan_(plan)
    ,left_executor_(std::move(left_executor))
    ,right_executor_(std::move(right_executor)){}


/*
 *  先计算出两侧的结果，然后遍历结果，将匹配的行join在以器，并将结果保存在result中
 *  针对left_executor和right_executor两个处理，对其中匹配的内容进行计算，并将结果保存到result中
 *
 * */
void NestedLoopJoinExecutor::Init() {
  Tuple left_tuple;
  RID left_rid;
  Tuple right_tuple;
  RID right_rid;

  // 分别循环执行查询
  left_executor_->Init();
  while(left_executor_->Next(&left_tuple,&left_rid)){
    right_executor_->Init();
    while(right_executor_->Next(&right_tuple,&right_rid)){
      // 计算链接条件
      if(plan_->Predicate()== nullptr || plan_->Predicate()->EvaluateJoin(
                        &left_tuple,left_executor_->GetOutputSchema(),
                        &right_tuple,right_executor_->GetOutputSchema()).GetAs<bool>()){
        // 计算要输出的列
        std::vector<Value> output;
        for(const auto &col:GetOutputSchema()->GetColumns()){
            output.push_back(col.GetExpr()->EvaluateJoin(
              &left_tuple,left_executor_->GetOutputSchema(),
              &right_tuple,right_executor_->GetOutputSchema()));
        }
        result_.emplace_back(Tuple(output,GetOutputSchema()));
      }
    }
  }
}

bool NestedLoopJoinExecutor::Next(Tuple *tuple, RID *rid) {
  if(now_id_<result_.size()){
    *tuple = result_[now_id_];
    *rid = tuple->GetRid();
    now_id_++;
    return true;
  }
  return false;
}

}  // namespace bustub
